package latticensprings;

import java.util.ArrayList;

import processing.core.PApplet;
import processing.core.PVector;

import toxi.geom.Vec3D;
import toxi.physics.*;

public class Creature {
	
	VerletParticle center;
	
	PVector centerVelocity;
	PVector centerAcceleration;
	
	float energy;
	float maxSpeed;
	float DIM;
	float phiValue;
	float thetaValue;
	
	ArrayList<VerletParticle>points;
	ArrayList<VerletSpring>bonds;
	
	int pointCount;
	float radius;
	float centerSpringLen;
	float centerSpringStr;
	
	
	int age;
	boolean isReady;
	PApplet parent;
	
	String DNA;
	
	Creature(PApplet _p, Vec3D _origin, float _rds, float _phi, float _theta, int _size, float _DIM)
	{
		parent = _p;
		center = new VerletParticle(_origin);
		phiValue = _phi;
		thetaValue = _theta;
		radius = _rds;
		pointCount = _size;
		points = new ArrayList<VerletParticle>();
		DIM = _DIM;
		
		center.lock();
		points.add(center);
		centerSpringLen = radius;
		centerSpringStr = 1.0f;
		isReady = false;
		age = 0;
		
		initPoints();
		initCenterBonds();
		
		//To be fixed to get from constructor
		maxSpeed = 3.0f;
		centerVelocity = new PVector(parent.random(-1.0f,1.0f), parent.random(-1.0f,1.0f), parent.random(-1.0f,1.0f));
		centerAcceleration = new PVector(parent.random(-0.2f,0.2f),parent.random(-0.2f,0.2f),parent.random(-0.2f,0.2f));
	}
	
	Creature(PApplet _p, Vec3D _origin, float _rds, float _phi, float _theta, int _size)
	{
		parent = _p;
		center = new VerletParticle(_origin);
		phiValue = _phi;
		thetaValue = _theta;
		radius = _rds;
		pointCount = _size;
		points = new ArrayList<VerletParticle>();
		center.lock();
		points.add(center);
		centerSpringLen = radius;
		centerSpringStr = 1.0f;
		isReady = false;
		age = 0;
		initPoints();
		initCenterBonds();
		
		//To be fixed to get from constructor
		maxSpeed = 3.0f;
		centerVelocity = new PVector(parent.random(-1.0f,1.0f), parent.random(-1.0f,1.0f), parent.random(-1.0f,1.0f));
		centerAcceleration = new PVector(parent.random(-0.2f,0.2f),parent.random(-0.2f,0.2f),parent.random(-0.2f,0.2f));
	}
	
	Creature(PApplet _p, String _dNA, Vec3D _origin)
	{
		parent = _p;
		DNA = _dNA;
		center = new VerletParticle(_origin);
		
		
		
	}
	
	String getDNA()
	{
		return DNA;
	}
	
	void initCenterBonds()
	{
		bonds = new ArrayList<VerletSpring>();
		if(points.size()>1)
		{
			VerletParticle cntr = points.get(0);
			for(int i=1;i<points.size();i++)
			{
				VerletParticle tP = points.get(i);
				centerSpringLen = parent.random(10,radius);
				VerletSpring cS = new VerletSpring(cntr, tP, centerSpringLen, centerSpringStr);
				bonds.add(cS);
			}
		}
	}
	void initPoints()
	{
	  float x,y,z;
	  float phi = phiValue;
	  float theta = thetaValue;
	  
	  //Vec3D center = new Vec3D();
	  
	  
	  for(int i=0; i<pointCount;i++)
	  {
	    float anglePhi, angleTheta;
	    anglePhi = PApplet.radians(phi * i);
	    angleTheta = PApplet.radians(theta * i);
	    x = center.x +radius * PApplet.sin(anglePhi) * PApplet.cos(angleTheta);
	    y = center.y +radius * PApplet.sin(anglePhi) * PApplet.sin(angleTheta);
	    z = center.z +radius * PApplet.cos(anglePhi);
	    
	    points.add(new VerletParticle(x,y,z));
	  }
	}
	
	void grow()
	{
		age += 1;
		
		if(age>350)
		{
			isReady = true;
		}
	}
	
	void update()
	{
		//PApplet.println("("+center.x+","+center.y+","+center.z+")");
//		if(center.x<299)
//		{
//			center.x += parent.random(-50,50);
//		}
//		if(center.y<299)
//		{
//			center.y += parent.random(-50,50);
//		}
//		if(center.z<299)
//		{
//			center.z += parent.random(-50,50);
//		}
//		
		PVector minLoc = new PVector(0.0f,0.0f,0.0f);
		PVector maxLoc = new PVector(DIM, DIM, DIM);
		PVector location = new PVector(center.x, center.y, center.z);
		centerAcceleration.set(new PVector(parent.random(-1.0f, 1.0f),parent.random(1.0f, 1.0f),parent.random(-0.5f, 0.5f)));
		if(location.x < 0 )
		{
			centerAcceleration.x *= -1;
		}
		if(location.x > DIM)
		{
			centerAcceleration.x *= -1;
		}
		
		if(location.y < 0)
		{
			centerAcceleration.y *= -1;
		}
		
		if(location.y >DIM)
		{
			centerAcceleration.y *=-1;
		}
		
		centerVelocity.add(centerAcceleration);
		centerVelocity.limit(maxSpeed);
		
		location.add(centerAcceleration);
		
		center.x = location.x;
		center.y = location.y; 
		center.z = location.z; 
	}
	
	ArrayList<VerletParticle> getCells()
	{
		return points;
	}
	ArrayList<VerletSpring>getBonds()
	{
		return bonds;
	}
	void displayBonds()
	{
		for(VerletSpring s : bonds)
		{
			parent.strokeWeight(1.0f);
			parent.stroke(90,120);
			parent.line(s.a.x,s.a.y,s.a.z, s.b.x, s.b.y, s.b.z);
		}
	}
	void display()
	{
		for(VerletParticle p : points)
		{
			parent.strokeWeight(4);
			if(p.isLocked())
			{
				parent.stroke(255,10, 56);
			}
			else
			{
				parent.stroke(255);
			}
			parent.point(p.x, p.y, p.z);
		}
		displayBonds();
	}
}
